/*
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Modified by Stefan Tillich, University of Bristol
 * - Adapted from RemoteSessionsHandler.java
 * - Changed package name
 */

package org.iacr.android.apps.yaea.io;

//import org.iacr.android.apps.yaea.io.RemoteRumpSessionHandler.Columns;

import org.iacr.android.apps.yaea.provider.ScheduleContract;
import org.iacr.android.apps.yaea.provider.ScheduleContract.RumpSession;
//import org.iacr.android.apps.yaea.provider.ScheduleContract.Sessions;
import org.iacr.android.apps.yaea.provider.ScheduleContract.SyncColumns;
//import org.iacr.android.apps.yaea.provider.ScheduleDatabase.SessionsSpeakers;
//import org.iacr.android.apps.yaea.provider.ScheduleDatabase.SessionsTracks;
import org.iacr.android.apps.yaea.util.Lists;
import org.iacr.android.apps.yaea.util.ParserUtils;
//import org.iacr.android.apps.yaea.util.SpreadsheetEntry;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;

import java.io.IOException;
import java.util.ArrayList;

import static org.iacr.android.apps.yaea.util.ParserUtils.sanitizeId;
//import static org.iacr.android.apps.yaea.util.ParserUtils.splitComma;
//import static org.iacr.android.apps.yaea.util.ParserUtils.translateTrackIdAlias;
import static org.iacr.android.apps.yaea.util.ParserUtils.AtomTags.CONTENT;
import static org.iacr.android.apps.yaea.util.ParserUtils.AtomTags.ENTRY;
import static org.iacr.android.apps.yaea.util.ParserUtils.AtomTags.UPDATED;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import static org.xmlpull.v1.XmlPullParser.TEXT;

/**
 * Handle a remote {@link XmlPullParser} that defines a set of rump session
 * talks.
 */
public class RemoteRumpSessionHandler extends XmlHandler {
    private static final String TAG = "RumpSessionHandler";
    


    public RemoteRumpSessionHandler() {
        super(ScheduleContract.CONTENT_AUTHORITY);
    }

    /** {@inheritDoc} */
    @Override
    public ArrayList<ContentProviderOperation> parse(XmlPullParser parser, ContentResolver resolver)
            throws XmlPullParserException, IOException {
        final ArrayList<ContentProviderOperation> batch = Lists.newArrayList();

        // Walk document, parsing any incoming entries
        int type;
        while ((type = parser.next()) != END_DOCUMENT) {
        	
        	long updated = -1;
        	String title = "";
        	String author = "";
        	int order = -1;
        	
            if (type == START_TAG && Columns.RS_TALK.equals(parser.getName())) {
            	
            	final int depth = parser.getDepth();

                String tag = null;
                int type_local;
                while (((type_local = parser.next()) != END_TAG ||
                        parser.getDepth() > depth) && type_local != END_DOCUMENT) {
                    if (type_local == START_TAG) {
                        tag = parser.getName();
                    } else if (type_local == END_TAG) {
                        tag = null;
                    } else if (type_local == TEXT) {
                        if (UPDATED.equals(tag)) {
                            final String text = parser.getText();
                            updated = ParserUtils.parseTime(text);
                        } else if (Columns.RS_TITLE.equals(tag)) {
                            title = parser.getText();
                        } else if (Columns.RS_AUTHOR.equals(tag)) {
                            author = parser.getText();
                        } else if (Columns.RS_ORDER.equals(tag)) {
                            order = Integer.parseInt(parser.getText());
                        }
                    }
                }             
 
                final String rumpSessionTalkId = sanitizeId(Integer.toString(order));
                final Uri rumpSessionTalkUri = RumpSession.buildRumpSessionTalkUri(rumpSessionTalkId);
                
                // Check for existing details, only update when changed
                final ContentValues values = queryRumpSessionTalkDetails(rumpSessionTalkUri, resolver);
                final long localUpdated = values.getAsLong(SyncColumns.UPDATED);
                final long serverUpdated = updated;

                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "found rump session talk " + author + ": " + title + " (order: " + order + ")");
                    Log.v(TAG, "found localUpdated=" + localUpdated + ", server=" + serverUpdated);
                }
                if (localUpdated >= serverUpdated) continue;
                		
                // Clear any existing values for this rump session talk, treating the
                // incoming details as authoritative.
                batch.add(ContentProviderOperation.newDelete(rumpSessionTalkUri).build());

                final ContentProviderOperation.Builder builder = ContentProviderOperation
                        .newInsert(RumpSession.CONTENT_URI);
                //final ContentProviderOperation.Builder builder = ContentProviderOperation
                //        .newUpdate(Sessions.CONTENT_URI);  
                
                builder.withValue(SyncColumns.UPDATED, serverUpdated);
                builder.withValue(RumpSession.RUMPSESSION_SPEAKER, author);
                builder.withValue(RumpSession.RUMPSESSION_TITLE, title);
                builder.withValue(RumpSession.RUMPSESSION_ORDER, order);
                builder.withValue(RumpSession.RUMPSESSION_VOTE, 0);

                // Rump session talk details ready, write to provider
                batch.add(builder.build());

                // Assign speakers
                /*
                final String[] speakers = splitComma(entry.get(Columns.SESSION_SPEAKERS));
                for (String speaker : speakers) {
                    final String speakerId = sanitizeId(speaker, true);
                    batch.add(ContentProviderOperation.newInsert(sessionSpeakersUri)
                            .withValue(SessionsSpeakers.SESSION_ID, sessionId)
                            .withValue(SessionsSpeakers.SPEAKER_ID, speakerId).build());
                }
                */
            }
        }

        return batch;
    }

    private static ContentValues queryRumpSessionTalkDetails(Uri uri, ContentResolver resolver) {
        final ContentValues values = new ContentValues();
        final Cursor cursor = resolver.query(uri, RumpSessionQuery.PROJECTION, null, null, null);
        try {
            if (cursor.moveToFirst()) {
                values.put(SyncColumns.UPDATED, cursor.getLong(RumpSessionQuery.UPDATED));
            } else {
                values.put(SyncColumns.UPDATED, ScheduleContract.UPDATED_NEVER);
            }
        } finally {
            cursor.close();
        }
        return values;
    }

    private interface RumpSessionQuery {
        String[] PROJECTION = {
                SyncColumns.UPDATED,
        };

        int UPDATED = 0;
    }

    /** Columns coming from remote XML file. */
    private interface Columns {
        String RS_TALK = "Talk";
        String RS_TITLE = "Title";
        String RS_AUTHOR = "Author";
        String RS_ORDER = "Order";
    }
}
